<?php
/**
 * Created by PhpStorm.
 * User: lzy
 * Date: 2018/11/1
 * Time: 15:40
 */

namespace App\Weixin\Repositories;

use App\Admin\Contracts\MemberInterface;
use App\Admin\Contracts\MemberLevelInterface;
use App\Base\Helpers\Lib\WxXiaoLibrary;
use App\Content\Models\BulletinModel;
use App\FreeBird\Models\CollectionModel;
use App\FreeBird\Models\MessageModel;
use App\FreeBird\Models\RebateLogModel;
use App\FreeBird\Models\StoreModel;
use App\Weixin\Contracts\UserInterface;
use App\Weixin\Exceptions\UserException;
use App\Weixin\Models\UserBalanceLogModel;
use App\Weixin\Models\UserScoreLogModel;
use App\Weixin\Models\WeixinUserIsvipModel;
use App\Weixin\Models\WeixinUserModel;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Request;

/**
 * 微信用户接口
 * Class DbUserRepositories
 * @package App\Weixin\Repositories
 */
class DbUserRepositories implements UserInterface
{


    /**
     * 用户中心接口
     * @return MemberInterface
     */
    public function getMemberInterface()
    {
        return app()->make(MemberInterface::class);
    }


    /**
     * 权限层级
     * @return MemberLevelInterface
     */
    public function getMemberLevelInterface()
    {
        return app(MemberLevelInterface::class);
    }

    /**
     * 微信用户模型
     * @return WeixinUserModel
     */
    public function getWeixinUserModel()
    {
        return app()->make(WeixinUserModel::class);
    }

    /**
     * 余额日志模型
     * @return UserBalanceLogModel
     */
    public function getUserBalanceLogModel()
    {
        return app()->make(UserBalanceLogModel::class);
    }


    /**
     * 金币日志模型
     * @return UserScoreLogModel
     */
    public function getUserScoreLogModel()
    {
        return app()->make(UserScoreLogModel::class);
    }

    /**
     * 用户vip模型
     * @return WeixinUserIsvipModel
     */
    public function getWeixinUserIsvipModel()
    {
        return app()->make(WeixinUserIsvipModel::class);
    }

    /**
     * 获取列表
     * @param $where
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function getList($where)
    {
        $request = Request::instance();
        $limit = empty($request->input("limit")) ? 10 : $request->input("limit");
        return $this->getWeixinUserModel()->newQuery()->where($where)->paginate($limit);
    }

    /**
     * 获取用户信息
     * @param $uid
     * @return mixed|void
     */
    public function getUserInfoById($uid)
    {
        return $this->getWeixinUserModel()->newQuery()->where("uid", $uid)->first();
    }

    public function getOpenIdByUid($uid)
    {

        return $this->getMemberInterface()->getOpenIdByUid($uid);
    }

    /**
     * 更新用户信息
     * @param $where
     * @param $data
     * @return int|mixed
     */
    public function updateXiaoUserInfo($where, $data)
    {
        //去掉金币更新
        unset($data['score']);
        unset($data['experience']);
        unset($data['token']);
        $data["update_time"] = time();  //更新当前时间
        return $this->getWeixinUserModel()->newQuery()->where($where)->update($data);
    }


    /**
     * 小程序登陆
     * @param $data
     */
    public function wxXiaoUserLogin($data)
    {

        $code = $data['code'];
        $appId = get_config_param_value('XIAO_APP_ID');//"wxc85f58f3d5d2dddb";//get_config_param_value('XIAO_APP_ID');//'wx4f4bc4dec97d474b';//get_config_param_value('XIAO_APP_ID')
        $appSecert = get_config_param_value('XIAO_APP_SECRET');//"d60bb73fa1619f15a41c030dc1e23dfd";//get_config_param_value('XIAO_APP_SECRET');//'tiihtNczf5v6AKRyjwEUhQ==2';               //get_config_param_value('XIAO_APP_SECRET')
        $encryptedData = $data['encryptedData'];  //"jKjHK/QIIX2FQs6/UIOV90J1c3bThpnALxXvHDbLGAUQJ74XlHJYSfyFQ3pU8wnVzd5YDJbYBCDgHRuHp6oJQkS3v4GQxX70y7LiaspSlErc17wO/GFT+OrZHIlNtwoDZkLynrJ0ocprophvr/n/ptTmYMKeQwBwMAANnj9A1A+8w24IN0swvdTceJSiag3n0sAFekAiKI9OlBpWCoHTpy/G/BaOAnOCYhrsdcy+YojTGlMWsTwi/qAR9p7E6XjDbrNHwa1cRNNork3k+rWfDVeYe10cNk/WLJWPJIUQ1ASWEscyruDK9sa+sQJIxzdI27RZoqyLGeCNOSKd7wa3THZtcT5Go/3b9IvsGMzDAHE1HRah1df9aks46S0+/qcjby8pLb6I142eP6eVTzN0IYUce9FwbRDLdZuuGHcIj0Ob4bGjZ0bW5yDRrB9j7+Pl3Iqf3SqI4KR8nlrv1awzmoaq0ErbosOVBLkiexgBSrw=";
        $iv = $data['iv'];//'xMxF3ngSr0FJJMqy+hvpiA==';
        $wxXiaoLibrary = new WxXiaoLibrary($appId, $appSecert);
        $data = $wxXiaoLibrary->decryptData($encryptedData, $iv, $code, $data);  //解密
        return $this->setWxUserInfo($data);
    }

    private function setWxUserInfo($jsonData)
    {
        $data = json_decode($jsonData, true);
        //清去用户缓存
        //Cache::forget("member:ucentermeber:user_accout_" . $data["id"]);
        $ucInfo = $this->getMemberInterface()->findUcenterMember(["username" => $data["openId"]]);


        if (empty($ucInfo)) {
            $ucdata = [];
            $ucdata["username"] = $data["openId"];
            $ucdata["password"] = "123456";
            $ucdata["reg_time"] = time();
            $ucdata["reg_ip"] = getClientIp(1);
            //如果没则新增一个用户
            if ($turnData = $this->getMemberInterface()->addUcenterMemberData($ucdata)) {

                $data["uid"] = $turnData->id;
                $data["nickname"] = $data["nickName"];
                //$data["truename"] = deal_emoji($data["nickName"], 0);
                $data["sex"] = $data['gender'];
                $data["headimgurl"] = $data["avatarUrl"];
                $data["city"] = $data["city"];
                $data["province"] = $data["province"];
                $data["country"] = $data["country"];
                $data["language"] = $data["language"];
                $data["lid"] = 1;
                if ($this->updateOrCreateWxUser($data)) {
                    $uid = $turnData->id;
                } else {
                    throw new UserException(UserException::EROOR_UMCENTER_ADD);
                }
            }
        } else {
            $ucdata = [];
            $ucdata["last_login_time"] = time();
            $ucdata["last_login_ip"] = getClientIp(1);
            $this->getMemberInterface()->updateUcenterMember(["id" => $ucInfo->id], $ucdata);
            $uid = $ucInfo->id;
        }


        if (empty($uid)) {
            throw new UserException(UserException::EROOR_UMCENTER_CACHE);
            //抛出异常
        } else {
            $token = $this->genToken();
            $key = WeixinUserModel::CACHE_KEY . $token;
            Cache::forever($key, $uid);
            Cache::forever($uid, $key);
            return $token;
        }
    }

    /**
     * 获取一个token值
     * @param int $len 长度，默认32位
     * @param bool $md5 默认使用md5算法
     * @return string 一个32为的token串
     */
    function genToken($len = 32, $md5 = true)
    {
        # Seed random number generator
        # Only needed for PHP versions prior to 4.2
        mt_srand((double)microtime() * 1000000);
        # Array of characters, adjust as desired
        $chars = array(
            'Q', '@', '8', 'y', '%', '^', '5', 'Z', '(', 'G', '_', 'O', '`',
            'S', '-', 'N', '<', 'D', '{', '}', '[', ']', 'h', ';', 'W', '.',
            '/', '|', ':', '1', 'E', 'L', '4', '&', '6', '7', '#', '9', 'a',
            'A', 'b', 'B', '~', 'C', 'd', '>', 'e', '2', 'f', 'P', 'g', ')',
            '?', 'H', 'i', 'X', 'U', 'J', 'k', 'r', 'l', '3', 't', 'M', 'n',
            '=', 'o', '+', 'p', 'F', 'q', '!', 'K', 'R', 's', 'c', 'm', 'T',
            'v', 'j', 'u', 'V', 'w', ',', 'x', 'I', '$', 'Y', 'z', '*'
        );
        # Array indice friendly number of chars;
        $numChars = count($chars) - 1;
        $token = '';
        # Create random token at the specified length
        for ($i = 0; $i < $len; $i++)
            $token .= $chars[mt_rand(0, $numChars)];
        # Should token be run through md5?
        if ($md5) {
            # Number of 32 char chunks
            $chunks = ceil(strlen($token) / 32);
            $md5token = '';
            # Run each chunk through md5
            for ($i = 1; $i <= $chunks; $i++)
                $md5token .= md5(substr($token, $i * 32 - 32, 32));
            # Trim the token
            $token = substr($md5token, 0, $len);
        }
        return $token;
    }


    public function updateOrCreateWxUser($data)
    {
        return $this->getWeixinUserModel()->newQuery()->updateOrCreate(['uid' => $data['uid']], $data);
    }

    /**
     * 更新用户余额
     * @param $uid
     * @param $amount
     * @param $type
     * @param $linkId  来源id
     * @return mixed|void
     */
    public function updateUserBalance($uid, $amount, $type, $linkId = 0, $remark = '')
    {

        if ($this->getWeixinUserModel()->newQuery()->where("uid", $uid)->update(['balance' => DB::raw('balance+' . $amount)])) {  //如果更新成功－则提交到历史记录

            return $this->setUserBalanceLog($uid, $amount, $type, $linkId, $remark);
        }
    }

    /**
     * 更新到用户余额变动表
     * @param $uid  变动用户
     * @param $amont  变动金额
     * @param $type  操作数据变动的类型
     */
    public function setUserBalanceLog($uid, $amont, $type, $linkId, $remark)
    {
        $data = array();
        $data['title'] = $this->getUserBalanceLogModel()->getTypeName($type);
        $data["order_sn"] = $this->makePaySn($uid);  //新增订单号
        $data["uid"] = $uid;
        $data["amount"] = $amont;
        $data["type"] = $type;
        $data["source_id"] = $linkId;
        $data["remark"] = $remark;
        return $this->getUserBalanceLogModel()->newQuery()->create($data);
    }

    /**
     * 变更金币
     * @param $where
     * @param $mount
     * @param $type
     * @param int $linkId
     * @param string $remark
     * @return mixed|void
     */
    public function updateUserScore($uid, $amount, $type, $linkId = 0, $remark = '')
    {
        if ($this->getWeixinUserModel()->newQuery()->where("uid", $uid)->update(['score' => DB::raw('score+' . $amount)])) {  //如果更新成功－则提交到历史记录
            return $this->setUserScoreLog($uid, $amount, $type, $linkId, $remark);
        }
    }

    /**
     * 金币变更表
     * @param $uid
     * @param $amont
     * @param $type
     * @param $linkId
     * @param $remark
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
     */
    public function setUserScoreLog($uid, $amont, $type, $linkId, $remark)
    {
        $data = array();
        $data['title'] = $this->getUserScoreLogModel()->getTypeName($type);
        $data['order_sn'] = $this->makePaySn($uid);
        $data["uid"] = $uid;
        $data["amount"] = $amont;
        $data["type"] = $type;
        $data["source_id"] = $linkId;
        $data["remark"] = $remark;
        return $this->getUserScoreLogModel()->newQuery()->create($data);
    }

    /**
     * 余额
     * @param $where
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|mixed
     */

    public function getBalanceLogList($where)
    {
        $request = Request::instance();
        $limit = empty($request->input("limit")) ? 10 : $request->input("limit");
        $sort = empty($request->input("sort")) ? 'create_time' : $request->input("sort");
        $order = empty($request->input("order")) ? 'asc' : $request->input("order");
        return $this->getUserBalanceLogModel()->newQuery()->where($where)->orderBy($sort, $order)->paginate($limit);
    }

    /**
     * 验证短信与手机号
     * @param $mobile
     * @param $code
     * @return bool
     */
    public function checkMobile($mobile, $code)
    {
        if (empty($mobile)) {
            throw  new ApiException([1001, "手机号必须的"]);
        }
        if (empty($code)) {
            throw  new ApiException([1001, "验证码必须的"]);
        }
        $key = md5($code . $mobile);
        $checkCode = Cache::get($key);
        if ($code == $checkCode) {
            return true;
        } else {
            return false;
        }
    }


    public function testWx($data)
    {
        $appId = get_config_param_value('XIAO_APP_ID');
        $appSecert = get_config_param_value('XIAO_APP_SECRET');
        $wxXiaoLibrary = new WxXiaoLibrary($appId, $appSecert);
        $wxXiaoLibrary->getAccessToken();

    }


    /***
     * 查询用户列表
     * @param $where
     * @return mixed|void
     */
    public function getUserList($where)
    {
        return $this->getWeixinUserModel()->newQuery()->where($where)->get();
    }


    /**
     * 获取用户信息
     * @param $where
     */
    public function getUserInfoByIdLib($where)
    {
        return $this->getWeixinUserModel()->newQuery()->where($where)->first();
    }


    /**
     * 更新直推与间推
     * @param $uid 用户
     * @param $pUid 直推uid
     * @return mixed|void
     */
    public function updatePushUserGrade($uid, $pUid)
    {
        if ($uid == $pUid) {
            throw new UserException(UserException::ERROR_PUSH_USER_SAME);
        }
        $pUserInfo = $this->getWeixinUserModel()->newQuery()->where("uid", $pUid)->first();
        $data["p1"] = $pUid;
        if (empty($pUserInfo)) {
            throw new UserException(UserException::ERROR_USER_EXITS);
        }
        if ($pUserInfo->p1) {
            $data["p2"] = $pUserInfo->p1;
        }
        return $this->getWeixinUserModel()->newQuery()->where("uid", $uid)->update($data);
    }

    /**
     * 间推与直推统计
     * @return RebateLogModel
     */
    public function getRebateLogModel(){
        return app()->make(RebateLogModel::class);
    }

    /**
     * 消息
     * @return MessageModel
     */
    public function getMessageModel(){
        return app()->make(MessageModel::class);
    }

    /**
     * 收藏
     * @return CollectionModel
     */
    public function getCollectionModel(){
        return app()->make(CollectionModel::class);
    }

    /**
     * 商家数
     * @return StoreModel
     */
    public function getStoreModel(){
        return app()->make(StoreModel::class);
    }

    /**
     * 商家数
     * @return BulletinModel
     */
    public function getBulletinModel(){
      return  app()->make(BulletinModel::class);
    }
    /**
     * 获取统计信息
     * @param $data
     */
    public function getInfoStatistics($data)
    {
        $returnArr=array();
        //统计是否是vipinfoStatistics
        $time = time();
        $lid = empty($data['lid']) ? 1 : $data['lid'];
        $info=$this->getWeixinUserIsvipModel()->newQuery()->where("uid",AUID)->where("lid", $lid)->where("start_time", "<=", $time)->where("end_time", ">=", $time)->first();
        if(empty($info)){
            //是否vip
            $returnArr["is_vip"]=0;
            $returnArr["vip_time"]='';
        }else{
            $returnArr["is_vip"]=1;
            $returnArr["vip_end_time"]=$info->end_time;
        }
        $returnArr["fei_amount"]=$this->getRebateLogModel()->newQuery()->where("buid",AUID)->whereIn("source_type",[1,2])->sum("b_mount"); //分销的总
        $returnArr['message_count']=$this->getMessageModel()->newQuery()->where("uid",[0,AUID])->count();  //消息数
        $returnArr["collection_count"] =$this->getCollectionModel()->newQuery()->where("uid",AUID)->count(); //收藏数
        $returnArr["store_count"] =$this->getStoreModel()->newQuery()->where("uid",AUID)->count(); //商家总数
        $returnArr["bulletin_count"]=$this->getBulletinModel()->newQuery()->whereIn("lid",[0,$lid])->count();
        return $returnArr;
    }


    /**
     * 获取用户信息含评论
     * @param $where
     * @return mixed|void
     */
    public function getDetail($where)
    {
        $request = Request::instance();
        $limit = empty($request->input("limit")) ? 10 : $request->input("limit");
        $sort = empty($request->input("sort")) ? 'create_time' : $request->input("sort");
        $order = empty($request->input("order")) ? 'desc' : $request->input("order");
        return $this->getWeixinUserModel()->newQuery()->with(["comment" => function ($query) use ($limit, $sort, $order) {
            $query->orderBy($sort, $order);
            $query->paginate($limit);
        }])->first();
    }

    /**
     * 修改状态
     * @param $where
     * @param $data
     * @return mixed|void
     */
    public function changeStatus($where, $data)
    {
        return $this->getWeixinUserModel()->newQuery()->where($where)->update($data);
    }



    /**
     * 生成支付单编号(两位随机 + 从2000-01-01 00:00:00 到现在的秒数+微秒+会员ID%1000)，该值会传给第三方支付接口
     * 长度 =2位 + 10位 + 3位 + 3位  = 18位
     * 1000个会员同一微秒提订单，重复机率为1/100
     * @return string
     */
    function makePaySn($member_id)
    {
        return mt_rand(10, 99)
            . sprintf('%010d', time() - 946656000)
            . sprintf('%03d', (float)microtime() * 1000)
            //. sprintf('%03d', (int) $member_id % 1000);
            . $member_id;
    }




//    /**
//     * 成功通知后调用此接口
//     * 用户购买vip
//     * @param $data
//     */
//    public function setUserBuyVip($data)
//    {
//
//        $data["uid"]=AUID;
////        $token= $this->genToken();
////        $key = WeixinUserModel::CACHE_KEY . $token;
////        Cache::forever($key, 16);
////        return $token;
//        $month = $data["month"];  //购买的月份
//        //判断是否是Vip
//        $time = time();
//        $userVipInfo = $this->getWeixinUserIsvipModel()->newQuery()->where("uid", $data["uid"])->where("start_time", ">=", $time)->where("end_time", "<=", $time)->first();  //用户是否已是Vip如果是则加上vip
//        if (!empty($userVipInfo)) {
//            $data["id"] = $userVipInfo->id;
//            $endTime = $userVipInfo->end_time; //结束时间
//            $endTime = strtotime("+" . $month . " month", $endTime);
//            $data["end_time"] = $endTime;
//        } else {
//            $data["id"] = null;
//            $data["start_time"] = $time;
//            $data["end_time"] = strtotime("+" . $month . " month", $time);
//        }
//        $data["lid"] = empty($data["lid"]) ? 1 : $data["lid"];
//        $moeny=400;
//        //记录统计vip统计次数
//        $udata=array();
//        $udata["vip_pay_times"]=DB::raw("vip_pay_times+1");
//        $udata["vip_pay_amount"]=DB::raw("vip_pay_amount+".$moeny);
//       $this->getMemberLevelInterface()->updateData(["id"=>$data["lid"]],$udata);
//        return $this->getWeixinUserIsvipModel()->newQuery()->updateOrCreate(["id" => $data["id"]], $data);
//    }
    public function getUserInfoByIdSelect($uid,$select){
        return $this->getWeixinUserModel()->newQuery()->select($select)->where("uid", $uid)->first();
        return $this->getWeixinUserModel()->newQuery()->select($select)->where("uid",$uid)->first();
    }

}